package com.just.fun.swordOffer;

/**
 * 二维数组查找
 * 在一个二维数组中，每一行都按照从左到右递增的顺序排序，每一列 都按照从上到下递增的顺序排序。
 * 请完成一个函数，输入这样的一个二维数组和一 个整数，判断数组中是否含有该整数。
 * 思路：从右上角或左下角开始找，逐行排除，或者用二分法查找
 */
public class TwoFind {
    public static boolean find(int[][] arrays,int target){
        if(arrays==null || arrays.length==0){
            return false;
        }
        //每一行按照二分查找
        int col=arrays[0].length;
        int row=arrays.length;
        for (int i = 0; i < col; i++) {
            int left=0;
            int right=row-1;
            while (left<=right){
                int mid=(left+right)/2;
                if(arrays[mid][i]==target){
                    System.out.println("找到"+target+"位置:"+mid+","+i);
                    return true;
                }else if(arrays[mid][i]<target){
                    left=mid+1;
                }else if(arrays[mid][i]>target){
                    right=mid-1;
                }
            }
        }
        return false;
    }

    /**
     * 双指针
     * 时间复杂度：O(mn)，空间复杂度：O(1)
     * @param arrays
     * @param target
     * @return
     */
    public static boolean find2(int[][] arrays,int target){
        if(arrays==null || arrays.length==0){
            return false;
        }
        int row=0;
        int col=arrays[0].length-1;
        while (row<arrays.length && col>-1){
            if(arrays[row][col]==target){
                System.out.println("找到"+target+"位置:"+row+","+col);
                return true;
            }else if (arrays[row][col]>target){
                col--;
            }else{
                row++;
            }
        }
        return false;
    }

    /**
     * 终极二分查找法
     * 时间复杂度：O(log mn)，空间复杂度：O(1)
     * 可以看成一个一维数组，注意行列的index,总共m*n个数字
     * @param arrays
     * @param target
     * @return
     */
    public static boolean find3(int[][] arrays,int target){
        if(arrays==null || arrays.length==0){
            return false;
        }
        int m=arrays.length;
        int n=arrays[0].length;
        int left=0;
        int right=m*n-1;
        while (left<=right){
            int mid=left+(right-left)/2;
            int rowIndex=mid/n; //假设n=5,有几个5就在第几行
            int colIndex=mid%n; //假设n=5,列肯定在5之间，去除前k个5，取余
            if(arrays[rowIndex][colIndex]==target){
                System.out.println("找到"+target+"位置:"+rowIndex+","+colIndex);
                return true;
            }
            if(arrays[rowIndex][colIndex]<target){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return false;
    }


    public static void main(String[] args) {
        int[][] matrix= {{1,4,7,11,15},{2,5,8,12,19},{3,6,9,16,22},{10,13,14,17,24},{18,21,23,26,30}};
        int target=5;
        System.out.println(find(matrix,target));
        System.out.println(find2(matrix,target));
        System.out.println(find3(matrix,target));
    }
}
